package com.wanwu.channel.service.strategy;

import com.alibaba.fastjson.JSONObject;
import com.wanwu.channel.common.enums.PayType;
import com.wanwu.channel.common.util.RSA;
import com.wanwu.channel.common.util.TrueFalse;
import com.wanwu.channel.common.util.UtilDate;

import com.wanwu.channel.dto.vo.ApplyClearanceStrategyReqVo;
import com.wanwu.channel.dto.vo.PayQueryStrategyReqVo;
import com.wanwu.channel.dto.vo.PrepayStrategyReqVo;
import com.wanwu.channel.remote.alipay.config.ZfbGlobalConfiguration;
import com.wanwu.channel.remote.alipay.config.ZfbHKConfiguration;
import com.wanwu.channel.remote.alipay.util.AlipayCore;
import com.wanwu.channel.service.strategy.domain.CloseOrderStrategyResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

public abstract class AbstractStragy implements PayStrategy {

    private static Logger logger = LoggerFactory.getLogger(AlipayAppStrategy.class);

    private static final BigDecimal DIVISOR = new BigDecimal("100");

    protected Map<String, String> makeHeadParams(ZfbGlobalConfiguration zfbGlobalConfiguration,
                                                 String serviceName) {
        Map<String, String> stringMap = new HashMap<>();
        // 支付宝接口名
        stringMap.put("service", serviceName);
        // 签约合作者身份ID
        stringMap.put("partner", zfbGlobalConfiguration.getPid());
        // 参数编码， 固定值
        stringMap.put("_input_charset", zfbGlobalConfiguration.getInputCharset());
        // 签名类型，目前仅支持RSA,sign_type不参与签名
        stringMap.put("sign_type", zfbGlobalConfiguration.getSignType());
        return stringMap;
    }

    protected Map<String, String> makeHeadHKParams(ZfbHKConfiguration zfbHKConfiguration,
                                                   String serviceName) {
        Map<String, String> stringMap = new HashMap<>();
        // 支付宝接口名
        stringMap.put("service", serviceName);
        // 签约合作者身份ID
        stringMap.put("partner", zfbHKConfiguration.getPid());
        // 参数编码， 固定值
        stringMap.put("_input_charset", zfbHKConfiguration.getInputCharset());
        // 签名类型，目前仅支持RSA,sign_type不参与签名
        stringMap.put("sign_type", zfbHKConfiguration.getSignType());
        return stringMap;
    }


    protected String makeGlobalParam(PrepayStrategyReqVo req, ZfbGlobalConfiguration zfbGlobalConfiguration) {
        Map<String, String> stringMap = makeHeadParams(zfbGlobalConfiguration, zfbGlobalConfiguration.getPayService());
        // 币种
        stringMap.put("currency", req.getCurrency());
        // 只填FP
        stringMap.put("forex_biz", zfbGlobalConfiguration.getForexBiz());
        // 设置未付款交易的超时时间，一旦超时，该笔交易就会自动被关闭。
        stringMap.put("it_b_pay", zfbGlobalConfiguration.getItBPay());
        // 服务器异步通知页面路径
        stringMap.put("notify_url", zfbGlobalConfiguration.getPayNotifyUrl());
        // 商户网站唯一订单号
        stringMap.put("out_trade_no", req.getBizOrderNo());
        // 支付类型。默认值为：1（商品购买）。
        stringMap.put("payment_type", zfbGlobalConfiguration.getPaymentType());
        // 固定值
        stringMap.put("product_code", zfbGlobalConfiguration.getProductCode());
        // 二级商户网站地址
        stringMap.put("refer_url", req.getMerPageUrl());
        // 商品金额
        BigDecimal originToPay = req.getPayAmount();
        BigDecimal toPay = originToPay.divide(DIVISOR).setScale(2);
        stringMap.put("rmb_fee", toPay.toString());
        // 签约卖家支付宝账号
        stringMap.put("seller_id", zfbGlobalConfiguration.getSellerId());
        // 商品的简要介绍。特殊字符不支持。备注：本字段的值会在客户支付时被展示给客户。 如：婴儿服
        stringMap.put("subject", req.getOrderName());
        // 交易信息
        Map<String, Object> tradeInfoMap = new HashMap<>();
        tradeInfoMap.put("business_type", "4");
        tradeInfoMap.put("goods_info", req.getGoodsInfo());
        tradeInfoMap.put("total_quantity", req.getTotalNumber());
        stringMap.put("trade_information", JSONObject.toJSONString(tradeInfoMap));

        Map<String, String> sArray = AlipayCore.paraFilter(stringMap);

        String waitSign = AlipayCore.createLinkString(sArray);

        String sign = RSA.sign(waitSign, zfbGlobalConfiguration.getPrivateKey(), zfbGlobalConfiguration.getInputCharset());
        // sign值需要URLencode
        try {
            sign = URLEncoder.encode(sign, zfbGlobalConfiguration.getInputCharset());
        } catch (UnsupportedEncodingException e) {
            logger.error("alipayGlobal app sign encode error,ex:{}", e.getMessage());
        }
        stringMap.put("sign", sign);
        String sHtmlText = AlipayCore.createLinkString(stringMap);
        if (logger.isDebugEnabled()) {
            logger.debug("alipay参数信息:{}", sHtmlText);
        }
        return sHtmlText;
    }

    protected Map<String, String> makeGlobalQueryParam(PayQueryStrategyReqVo request, ZfbGlobalConfiguration zfbGlobalConfiguration) {
        Map<String, String> sParaTemp = makeHeadParams(zfbGlobalConfiguration, zfbGlobalConfiguration.getQueryService());
        String tradeNo = request.getThirdOrderNo();
        if (StringUtils.isNotBlank(tradeNo)) {
            sParaTemp.put("trade_no", tradeNo);
            return sParaTemp;
        }
        String outTradeNo = request.getBizOrderNo();
        if (StringUtils.isNotBlank(outTradeNo)) {
            sParaTemp.put("out_trade_no", outTradeNo);
        }
        logger.info("组装支付宝查询接口，请求参数：{}", JSONObject.toJSONString(sParaTemp));
        return sParaTemp;
    }

    protected Map<String, String> makeGlobalRefundParam(Map<String, Object> params, ZfbGlobalConfiguration zfbGlobalConfiguration) {
        Map<String, String> sParaTemp = makeHeadParams(zfbGlobalConfiguration, zfbGlobalConfiguration.getRefundService());
        sParaTemp.put("notify_url", zfbGlobalConfiguration.getRefundNotifyUrl());
        sParaTemp.put("out_return_no", (String) params.get("outReturnNo"));
        sParaTemp.put("out_trade_no", (String) params.get("outTradeNo"));
//        sParaTemp.put("return_amount", (String));
        BigDecimal originRefund = new BigDecimal((int) params.get("returnRmbAmount"));
        BigDecimal returnRmbAmount = originRefund.divide(DIVISOR).setScale(2);
        sParaTemp.put("return_rmb_amount", returnRmbAmount.toString());
        sParaTemp.put("gmt_return", UtilDate.getDateTimeLong());
        sParaTemp.put("currency", (String) params.get("currency"));
        sParaTemp.put("reason", (String) params.get("reason"));
        //sParaTemp.put("is_sync", AlipayConfig.is_sync);
        sParaTemp.put("product_code", zfbGlobalConfiguration.getProductCode());
        logger.info("组装支付宝退款接口，请求参数：{}", JSONObject.toJSONString(sParaTemp));
        return sParaTemp;
    }

    protected String makeHkParam(PrepayStrategyReqVo req, ZfbHKConfiguration zfbHKConfiguration) {
        Map<String, String> stringMap = makeHeadHKParams(zfbHKConfiguration, zfbHKConfiguration.getPayService());
        // 二级商户网站地址
        stringMap.put("refer_url", req.getMerPageUrl());
        // 服务器异步通知页面路径
        stringMap.put("notify_url", zfbHKConfiguration.getPayNotifyUrl());
        stringMap.put("payment_inst", zfbHKConfiguration.getPaymentInst());
        // 商户网站唯一订单号
        stringMap.put("out_trade_no", req.getBizOrderNo());
        // 商品的简要介绍。特殊字符不支持。备注：本字段的值会在客户支付时被展示给客户。 如：婴儿服
        stringMap.put("subject", req.getOrderName());
        // 支付类型。默认值为：1（商品购买）。
        stringMap.put("payment_type", zfbHKConfiguration.getPaymentType());
        // 签约卖家支付宝账号
        stringMap.put("seller_id", zfbHKConfiguration.getSellerId());
        // 商品金额
        BigDecimal originToPay = req.getPayAmount();
        BigDecimal toPay = originToPay.divide(DIVISOR).setScale(2);
        stringMap.put("total_fee", toPay.toString());
        // Detailed description about the goods. Special characters are not supported.
        stringMap.put("body", req.getGoodsDetailDescription());
        // 币种
        stringMap.put("currency", req.getCurrency());
        // 只填FP
        stringMap.put("forex_biz", zfbHKConfiguration.getForexBiz());
        // 设置未付款交易的超时时间，一旦超时，该笔交易就会自动被关闭。
        stringMap.put("it_b_pay", zfbHKConfiguration.getItBPay());
        // 固定值
        stringMap.put("product_code", zfbHKConfiguration.getProductCode());
        // 交易信息
        Map<String, Object> tradeInfoMap = new HashMap<>();
        tradeInfoMap.put("business_type", "4");
        tradeInfoMap.put("goods_info", req.getGoodsInfo());
        tradeInfoMap.put("total_quantity", req.getTotalNumber());
        stringMap.put("trade_information", JSONObject.toJSONString(tradeInfoMap));

        Map<String, String> sArray = AlipayCore.paraFilter(stringMap);

        String waitSign = AlipayCore.createLinkString(sArray);

        String sign = RSA.sign(waitSign, zfbHKConfiguration.getPrivateKey(), zfbHKConfiguration.getInputCharset());
        // sign值需要URLencode
        try {
            sign = URLEncoder.encode(sign, zfbHKConfiguration.getInputCharset());
        } catch (UnsupportedEncodingException e) {
            logger.error("alipayHK app sign encode error,ex:{}", e.getMessage());
        }
        stringMap.put("sign", sign);
        String sHtmlText = AlipayCore.createLinkString(stringMap);
        if (logger.isDebugEnabled()) {
            logger.debug("alipay参数信息:{}", sHtmlText);
        }
        return sHtmlText;
    }

    protected Map<String, String> makeHkRefundParam(Map<String, Object> params, ZfbHKConfiguration zfbHKConfiguration) {
        Map<String, String> sParaTemp = makeHeadHKParams(zfbHKConfiguration, zfbHKConfiguration.getRefundService());
        sParaTemp.put("notify_url", zfbHKConfiguration.getRefundNotifyUrl());
        sParaTemp.put("out_return_no", (String) params.get("outReturnNo"));
        sParaTemp.put("out_trade_no", (String) params.get("outTradeNo"));
//        sParaTemp.put("return_amount", (String));
        BigDecimal originRefund = new BigDecimal((String) params.get("returnRmbAmount"));
        BigDecimal returnRmbAmount = originRefund.divide(DIVISOR).setScale(2);
        sParaTemp.put("return_amount", returnRmbAmount.toString());
        sParaTemp.put("gmt_return", UtilDate.getDateTimeLong());
        sParaTemp.put("currency", (String) params.get("currency"));
        sParaTemp.put("reason", (String) params.get("reason"));
        sParaTemp.put("is_sync", zfbHKConfiguration.getIsSync());
//        sParaTemp.put("product_code", zfbHKConfiguration.getProductCode());
        logger.info("组装支付宝HK退款接口，请求参数：{}", JSONObject.toJSONString(sParaTemp));
        return sParaTemp;
    }

    protected Map<String, String> makeHkQueryParam(PayQueryStrategyReqVo request, ZfbHKConfiguration zfbHKConfiguration) {
        Map<String, String> sParaTemp = makeHeadHKParams(zfbHKConfiguration, zfbHKConfiguration.getQueryService());
        String tradeNo = request.getThirdOrderNo();
        if (StringUtils.isNotBlank(tradeNo)) {
            sParaTemp.put("trade_no", tradeNo);
            return sParaTemp;
        }
        String outTradeNo = request.getBizOrderNo();
        if (StringUtils.isNotBlank(outTradeNo)) {
            sParaTemp.put("out_trade_no", outTradeNo);
        }
        logger.info("组装支付宝HK查询接口，请求参数：{}", JSONObject.toJSONString(sParaTemp));
        return sParaTemp;
    }

    protected Map<String, String> makeApplyClearanceParam(ApplyClearanceStrategyReqVo req, String serviceName, String pid, String inputCharset) {
        Map<String, String> sParaTemp = new HashMap<String, String>();
        sParaTemp.put("service", serviceName);
        sParaTemp.put("partner", pid);
        sParaTemp.put("_input_charset", inputCharset);
        sParaTemp.put("out_request_no", req.getChannelNo());
        sParaTemp.put("trade_no", req.getThirdOrderNo());
        sParaTemp.put("merchant_customs_code", req.getMerchantCustomsCode());
        BigDecimal amount = req.getAmount();
        amount = amount.divide(DIVISOR).setScale(2);
        sParaTemp.put("amount", amount.toString());
        sParaTemp.put("customs_place", req.getCustomsPlace());
        sParaTemp.put("merchant_customs_name", req.getMerchantCustomsName());
        if (TrueFalse.T.equals(req.getIsSplit())) {
            sParaTemp.put("is_split", req.getIsSplit());
            sParaTemp.put("sub_out_biz_no", req.getSubOrderNo());
        }
        if (!StringUtils.isEmpty(req.getCertName())) {
            sParaTemp.put("buyer_name", req.getCertName());
        }
        if (!StringUtils.isEmpty(req.getCertId())) {
            sParaTemp.put("buyer_id_no", req.getCertId());
        }
        logger.info("组装支付宝申请报关接口，请求参数：{}", JSONObject.toJSONString(sParaTemp));
        return sParaTemp;
    }



    protected Map<String, String> makeQueryClearanceParam(ApplyClearanceStrategyReqVo req, String serviceName, String pid, String inputCharset) {
        Map<String, String> sParaTemp = new HashMap<String, String>();
        sParaTemp.put("service", serviceName);
        sParaTemp.put("partner", pid);
        sParaTemp.put("_input_charset", inputCharset);
        sParaTemp.put("out_request_nos", req.getChannelNo());
        return sParaTemp;
    }


}
